#include "ws2812.h"

#include "spi.h"

// 所有图片元数据在flash中的起始地址, 共32张图
const uint32_t Ws_addrList[] = {
    FLASH_PAGE_96,  FLASH_PAGE_97,  FLASH_PAGE_98,  FLASH_PAGE_99,
    FLASH_PAGE_100, FLASH_PAGE_101, FLASH_PAGE_102, FLASH_PAGE_103,
    FLASH_PAGE_104, FLASH_PAGE_105, FLASH_PAGE_106, FLASH_PAGE_107,
    FLASH_PAGE_108, FLASH_PAGE_109, FLASH_PAGE_110, FLASH_PAGE_111,
    FLASH_PAGE_112, FLASH_PAGE_113, FLASH_PAGE_114, FLASH_PAGE_115,
    FLASH_PAGE_116, FLASH_PAGE_117, FLASH_PAGE_118, FLASH_PAGE_119,
    FLASH_PAGE_120, FLASH_PAGE_121, FLASH_PAGE_122, FLASH_PAGE_123,
    FLASH_PAGE_124, FLASH_PAGE_125, FLASH_PAGE_126, FLASH_PAGE_127};

Ws_HandleTypeDef hws;

void Ws_Init(void) {
  hws.offset = 0;
  hws.reserve = 0;
  Ws_Clear();
  Ws_Load(hws.matrix.color);
  Ws_Draw();
}

// 重命名图像
void Ws_Rename(const uint8_t *name) {
  uint8_t i = 0;
  while (i < 15 && name[i] != '\0') {
    hws.matrix.name[i] = name[i];
    i++;
  }
  hws.matrix.name[i] = '\0';
  while (i < 16) {
    hws.matrix.name[i] = 0xFF;
    i++;
  }
}

// 全屏熄灭
void Ws_Clear(void) {
  for (uint8_t i = 0; i < 32; i++) {
    for (uint8_t j = 0; j < 8; j++) {
      hws.matrix.color[i][j][0] = 0;
      hws.matrix.color[i][j][1] = 0;
      hws.matrix.color[i][j][2] = 0;
    }
  }
}

// 将元数据按一定规则导入到待发送数组中
void Ws_Load(uint8_t color[32][8][3]) {
  for (uint8_t i = 0; i < PRE_LENGTH; i++) {
    for (uint8_t j = 0; j < 24; j++) {
      hws.buffer[i][j] = 0x00;
    }
  }
  uint8_t k, x, y;
  uint16_t idx;  // 如果idx用8位整型会溢出
  for (uint8_t i = 0; i < 32; i++) {
    for (uint8_t j = 0; j < 8; j++) {
      x = hws.reserve ? 31 - i : i;
      y = hws.reserve ? 7 - j : j;
      idx = PRE_LENGTH + (i * 8 + ((i & 1) ? (7 - j) : j));

      for (k = 0; k < 8; k++)
        hws.buffer[idx][k] =
            (((color[(x + hws.offset) % 32][y][0]) & (1 << (7 - k))) ? CODE_1
                                                                   : CODE_0);
      for (; k < 16; k++)
        hws.buffer[idx][k] =
            (((color[(x + hws.offset) % 32][y][1]) & (1 << (15 - k))) ? CODE_1
                                                                    : CODE_0);
      for (; k < 24; k++)
        hws.buffer[idx][k] =
            (((color[(x + hws.offset) % 32][y][2]) & (1 << (23 - k))) ? CODE_1
                                                                    : CODE_0);
    }
  }
  for (uint8_t i = 0; i < POST_LENGTH; i++) {
    for (uint8_t j = 0; j < 24; j++) {
      hws.buffer[PRE_LENGTH + 256 + i][j] = 0x00;
    }
  }
}

// 将待发送数组中的数据发送到WS2812屏幕, 即更新屏幕
void Ws_Draw(void) {
  // 避免发送时因SPI处于繁忙状态而直接返回
  while (HAL_SPI_GetState(&hspi2) != HAL_SPI_STATE_READY);
  // 这里使用了DMA不阻塞MCU, 同时防止SPI被中断打断
  HAL_SPI_Transmit_DMA(&hspi2, (uint8_t *)hws.buffer,
                       (PRE_LENGTH + 256 + POST_LENGTH) * 24);
}

void Ws_Save(uint8_t idx) {
  Flash_Erase(Ws_addrList[idx]);
  Flash_Write(Ws_addrList[idx], (uint16_t *)&hws.matrix, 512);
}

// 从flash中导入元数据
void Ws_Read(uint8_t idx) {
  uint16_t **tmp = (uint16_t **)(&Ws_addrList[idx]);
  uint16_t *ptr = (uint16_t *)(&hws.matrix);
  for (uint16_t i = 0; i < 512; i++) {
    ptr[i] = (*tmp)[i];
  }
}
